What is stream-http?
The stream-http npm package is designed to provide a streaming HTTP client for browser-based applications that mimics node's native http module, allowing for code that uses http to be more easily ported to the browser.
What are stream-http's main functionalities?
HTTP GET request
This feature allows you to perform an HTTP GET request and stream the response data as it is received.
const http = require('stream-http');
http.get('http://example.com', function (response) {
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
HTTP request with options
This feature allows you to perform an HTTP request with custom options such as method, path, and headers, and to send data in the body of the request.
const http = require('stream-http');
const options = {
method: 'POST',
path: '/submit',
headers: {'Content-Type': 'application/json'}
};
const req = http.request(options, function (response) {
console.log('STATUS: ' + response.statusCode);
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.write(JSON.stringify({ key: 'value' }));
req.end();
Handling request errors
This feature demonstrates how to handle errors that may occur during an HTTP request.
const http = require('stream-http');
http.get('http://example.com', function (response) {
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
}).on('error', function (e) {
console.error('Request failed: ' + e.message);
});
Other packages similar to stream-http
axios
Axios is a promise-based HTTP client for the browser and node.js. It provides a simple API for performing HTTP requests and is often preferred for its ease of use and promise support compared to stream-http.
fetch
The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipeline, such as requests and responses. It is built into modern browsers and offers a more modern, promise-based approach to asynchronous HTTP requests compared to stream-http.
superagent
Superagent is a small progressive client-side HTTP request library that offers a simple, fluent API. It is often used for its chaining syntax and built-in support for JSON, which can make it more convenient than stream-http for certain use cases.
got
Got is a human-friendly and powerful HTTP request library for Node.js. It is designed to be a simpler and more robust alternative to the built-in http module, with features like retries and streams, which can make it a more feature-rich alternative to stream-http.
stream-http
This module is an implementation of Node's native http
module for the browser.
It tries to match Node's API and behavior as closely as possible, but some features
aren't available, since browsers don't give nearly as much control over requests.
This is heavily inspired by, and intended to replace, http-browserify.
What does it do?
In accordance with its name, stream-http
tries to provide data to its caller before
the request has completed whenever possible.
Backpressure, allowing the browser to only pull data from the server as fast as it is
consumed, is supported in:
- Chrome >= 58 (using
fetch
and WritableStream
)
The following browsers support true streaming, where only a small amount of the request
has to be held in memory at once:
- Chrome >= 43 (using the
fetch
API) - Firefox >= 9 (using
moz-chunked-arraybuffer
responseType with xhr)
The following browsers support pseudo-streaming, where the data is available before the
request finishes, but the entire response must be held in memory:
- Chrome
- Safari >= 5, and maybe older
- IE >= 10
- Most other Webkit-based browsers, including the default Android browser
All browsers newer than IE8 support binary responses. All of the above browsers that
support true streaming or pseudo-streaming support that for binary data as well
except for IE10. Old (presto-based) Opera also does not support binary streaming either.
IE8 note:
As of version 2.0.0, IE8 support requires the user to supply polyfills for
Object.keys
, Array.prototype.forEach
, and Array.prototype.indexOf
. Example
implementations are provided in ie8-polyfill.js; alternately,
you may want to consider using es5-shim.
All browsers with full ES5 support shouldn't require any polyfills.
How do you use it?
The intent is to have the same API as the client part of the
Node HTTP module. The interfaces are the same wherever
practical, although limitations in browsers make an exact clone of the Node API impossible.
This module implements http.request
, http.get
, and most of http.ClientRequest
and http.IncomingMessage
in addition to http.METHODS
and http.STATUS_CODES
. See the
Node docs for how these work.
-
The message.url
property provides access to the final URL after all redirects. This
is useful since the browser follows all redirects silently, unlike Node. It is available
in Chrome 37 and newer, Firefox 32 and newer, and Safari 9 and newer.
-
The options.withCredentials
boolean flag, used to indicate if the browser should send
cookies or authentication information with a CORS request. Default false.
This module has to make some tradeoffs to support binary data and/or streaming. Generally,
the module can make a fairly good decision about which underlying browser features to use,
but sometimes it helps to get a little input from the developer.
-
The options.mode
field passed into http.request
or http.get
can take on one of the
following values:
- 'default' (or any falsy value, including
undefined
): Try to provide partial data before
the request completes, but not at the cost of correctness for binary data or correctness of
the 'content-type' response header. This mode will also avoid slower code paths whenever
possible, which is particularly useful when making large requests in a browser like Safari
that has a weaker JavaScript engine. - 'allow-wrong-content-type': Provides partial data in more cases than 'default', but
at the expense of causing the 'content-type' response header to be incorrectly reported
(as 'text/plain; charset=x-user-defined') in some browsers, notably Safari and Chrome 42
and older. Preserves binary data whenever possible. In some cases the implementation may
also be a bit slow. This was the default in versions of this module before 1.5.
- 'prefer-stream': Provide data before the request completes even if binary data (anything
that isn't a single-byte ASCII or UTF8 character) will be corrupted. Of course, this option
is only safe for text data. May also cause the 'content-type' response header to be
incorrectly reported (as 'text/plain; charset=x-user-defined').
- 'disable-fetch': Force the use of plain XHR regardless of the browser declaring a fetch
capability. Preserves the correctness of binary data and the 'content-type' response header.
- 'prefer-fast': Deprecated; now a synonym for 'default', which has the same performance
characteristics as this mode did in versions before 1.5.
-
options.requestTimeout
allows setting a timeout in millisecionds for XHR and fetch (if
supported by the browser). This is a limit on how long the entire process takes from
beginning to end. Note that this is not the same as the node setTimeout
functions,
which apply to pauses in data transfer over the underlying socket, or the node timeout
option, which applies to opening the connection.
Features missing compared to Node
http.Agent
is only a stub- The 'socket', 'connect', 'upgrade', and 'continue' events on
http.ClientRequest
. - Any operations, including
request.setTimeout
, that operate directly on the underlying
socket. - Any options that are disallowed for security reasons. This includes setting or getting
certain headers.
message.httpVersion
message.rawHeaders
is modified by the browser, and may not quite match what is sent by
the server.message.trailers
and message.rawTrailers
will remain empty.- Redirects are followed silently by the browser, so it isn't possible to access the 301/302
redirect pages.
- The
timeout
event/option and setTimeout
functions, which operate on the underlying
socket, are not available. However, see options.requestTimeout
above.
Example
http.get('/bundle.js', function (res) {
var div = document.getElementById('result');
div.innerHTML += 'GET /beep<br>';
res.on('data', function (buf) {
div.innerHTML += buf;
});
res.on('end', function () {
div.innerHTML += '<br>__END__';
});
})
Running tests
There are two sets of tests: the tests that run in Node (found in test/node
) and the tests
that run in the browser (found in test/browser
). Normally the browser tests run on
Sauce Labs.
Running npm test
will run both sets of tests, but in order for the Sauce Labs tests to run
you will need to sign up for an account (free for open source projects) and put the
credentials in a .zuulrc
file.
To run just the Node tests, run npm run test-node
.
To run the browser tests locally, run npm run test-browser-local
and point your browser to
http://localhost:8080/__zuul
License
MIT. Copyright (C) John Hiesey and other contributors.